﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace MakeIT.Deo.Negocios
{
    /// <summary>
    /// Classe que reune os métodos relativos ao Familia - Herda da classe base NegocioBase
    /// </summary>
    public class ProdutoBO
    {

        private deoEntities modelo = null;

        public ProdutoBO()
        {
            modelo = new deoEntities();
        }

        /// <summary>
        /// Salva um novo registro ou atualiza um já existente
        /// </summary>
        /// <param name="entidade">Objeto a ser gravado/atualizadao em banco de dados</param>
        /// <param name="novo">Determina se um novo registro ou não</param>
        public void SalvarProduto(produto entidade, Boolean novo)
        {
            try
            {

                // Verifica se eh um registro novo
                if (novo)
                {
                    // Insere o regisro na tabela de Familia
                    modelo.AddToproduto(entidade);
                }
                else
                {
                    //Efetiva as mudanças na entidade já existente
                    modelo.ApplyPropertyChanges(entidade.EntityKey.EntitySetName, entidade);
                }

                // Efetiva a trasação no Banco
                modelo.SaveChanges();
                
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public List<produto> RecuperaProduto(int? idProduto, string produto)
        {
            return RecuperaProduto(idProduto, produto, null, null, false);
        }

        /// <summary>
        /// Recupera uma lista de Produtos.
        /// </summary>
        /// <param name="idProduto">Codigo do Produto</param>
        /// <param name="produto">Nome do Produto</param>
        /// <param name="referencia">String de Referencia</param>
        /// <param name="idSubFamilia">Codigo da SubFamilia</param>
        /// <param name="simultaneoProdRef">Comparar Produto e Referencia simultaneamente</param>
        /// <returns>Lista de Produtos segundo o criterio dos parametros</returns>
        public List<produto> RecuperaProduto(int? idProduto, string produto, string referencia, int? idSubFamilia, bool simultaneoProdRef)
        {
            try
            {
                List<produto> listProduto = modelo.produto.ToList();
                List<produtoxsubfamilia> listProdutoXSubFamilia = RecuperaProdutoXSubFamilia(idProduto, idSubFamilia) ?? new List<produtoxsubfamilia>();
                listProduto = listProduto.Join(listProdutoXSubFamilia,
                    prod => prod.IdProduto,
                    pxsf => pxsf.IdProduto,
                    (prod, pxsf) => prod)
                    .ToList();
                if (!String.IsNullOrEmpty(produto) && !String.IsNullOrEmpty(referencia) && simultaneoProdRef)
                    listProduto = listProduto.Where(i => i.Produto.Contains(produto) || i.Referencia.Equals(referencia)).ToList();
                else
                {
                    if (!String.IsNullOrEmpty(produto)) listProduto = listProduto.Where(i => i.Produto.Contains(produto)).ToList();
                    if (!String.IsNullOrEmpty(referencia)) listProduto = listProduto.Where(i => i.Referencia.Equals(referencia)).ToList();
                }
                listProduto = listProduto.OrderBy(prod => prod.Referencia).ToList();
                return (listProduto.Count > 0) ? listProduto : null;
            }
            catch { throw; }
        }
        /*
        /// <summary>
        /// Recupera uma lista de Familia 
        /// </summary>
        /// <param name="idProduto">Codigo do Familia</param>
        /// <param name="nomeFamilia">Nome do familia usado no filtro da query (like)</param>
        /// <returns>Lista de Familia</returns>
        public List<produto> RecuperaProduto(int? idProduto, string produto, string referencia, int? idSubFamilia, bool simultaneoProdRef)
        {

            try
            {
                // Declara objetos
                IQueryable<produto> query = modelo.produto;

                // Verifica se o código do produto é diferente de nulo
                if (idProduto != null)
                {
                    // monta query dinamica
                    query = query.Where(a => a.IdProduto == idProduto);
                }
                // Verifica se o código do familia é diferente de nulo
                if (idSubFamilia != null)
                {
                    // monta query dinamica
                    query = query.Where(a => a.IdSubFamilia == idSubFamilia);
                }

                if (!string.IsNullOrEmpty(produto) && !string.IsNullOrEmpty(referencia) && simultaneoProdRef)
                {
                    query = query.Where(a => a.Produto.Contains(produto) || a.Referencia.Equals(referencia));
                }
                else
                {
                    // Verifica se filtro nomeproduto é diferente de vazio ou nulo
                    if (!string.IsNullOrEmpty(produto))
                    {
                        // monta query dinamica
                        query = query.Where(a => a.Produto.Contains(produto));
                    }

                    // Verifica se filtro email é diferente de vazio ou nulo
                    if (!string.IsNullOrEmpty(referencia))
                    {
                        // monta query dinamica
                        query = query.Where(a => a.Referencia.Equals(referencia));
                    }
                }

                // Executa Query
                var retornaLista = from prod in query
                                   join subfamilia in modelo.subfamilia on prod.IdSubFamilia equals subfamilia.IdSubFamilia
                                   orderby prod.Referencia
                                   select prod;
                /*{
                    CadastradoPor = subfam.CadastradoPor, 
                    EditadoPor = subfam.EditadoPor,
                    Cadastro = subfam.Cadastro,
                    Edicao = subfam.Edicao,
                    IdFamilia = subfam.IdFamilia
                    IdProduto = subfam.IdProduto, 
                    Referencia = subfam.Referencia, 
                    Produto = subfam.Produto,
                    fotog = subfam.fotog,
                    Fotop = subfam.Fotop,
                    Familia = familia.Familia
                }* /

                if (retornaLista.Count() > 0)
                {
                    return retornaLista.ToList();
                }
                else
                {
                    return null;
                }

            }
            catch (Exception e)
            {

                throw e; //TODO: Tratar a exceção
            }
        }
        */

        /// <summary>
        /// Recupera o Familia pelo código.
        /// </summary>
        /// <param name="idProduto">Código do Familia</param>
        /// <returns>Lista de familia</returns>
        public produto RecuperaProduto(int? idProduto)
        {
            List<produto> listaProduto = RecuperaProduto(idProduto, null, null, null, false);
            if (listaProduto != null && listaProduto.Count > 0)
                return listaProduto[0];
            else
                return null;
        }

        /// <summary>
        /// Recupera o Familia pelo nome (like)
        /// </summary>
        /// <param name="nomeFamilia">Nome do Familia</param>
        /// <returns>Lista de familias</returns>
        public List<produto> RecuperaProduto(string nomeProduto)
        {
            return RecuperaProduto(null, nomeProduto, null, null, false);
        }

        /// <summary>
        /// Recupera todos os registros Familia
        /// </summary>        
        /// <returns>Lista de Familias</returns>
        public List<produto> RecuperaProduto()
        {
            // chama o método de mesmo nome (overload) passando apenas o parametro pertinente
            return this.RecuperaProduto(null, null, null, null, false);
        }

        /// <summary>
        /// Excluir um determinado registro 
        /// </summary>
        /// <param name="entidade">Registro a ser excluido</param>
        /// <param name="msg"></param>
        /// <returns>Retorna uma msg quando há, a qual sinaliza algum fluxo alternativo</returns>
        public void DeletaProduto(produto produto)
        {
            try
            {
                EntityKey key = new EntityKey(modelo.DefaultContainerName + ".produto", "IdProduto", produto.IdProduto);
                modelo.DeleteObject(modelo.GetObjectByKey(key));
                modelo.SaveChanges();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        public List<produtoxcategoria> RecuperaProdutoXCategoria(int? idProduto, int? idCategoria)
        {
            try
            {
                // Declara objetos
                IQueryable<produtoxcategoria> query = modelo.produtoxcategoria;

                // Verifica se o código do produto é diferente de nulo
                if (idProduto != null)
                {
                    // monta query dinamica
                    query = query.Where(a => a.IdProduto == idProduto);
                }
                // Verifica se o código do categoria é diferente de nulo
                if (idCategoria != null)
                {
                    // monta query dinamica
                    query = query.Where(a => a.IdCategoria == idCategoria);
                }

                // Executa Query
                var retornaLista = from prod in query
                                   select prod;
            
                if (retornaLista.Count() > 0)
                {
                    return retornaLista.ToList();
                }
                else
                {
                    return null;
                }

            }
            catch (Exception e)
            {

                throw e; //TODO: Tratar a exceção
            }
        }

        public void DeletaProdutoxCategoria(produtoxcategoria produtoXCategoria)
        {
            try
            {
                EntityKey key = new EntityKey(modelo.DefaultContainerName + ".produtoxcategoria", "IdProdutoXCategoria", produtoXCategoria.IdProdutoXCategoria);
                modelo.DeleteObject(modelo.GetObjectByKey(key));
                modelo.SaveChanges();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public void DeletaProdutoxCategoria(List<produtoxcategoria> listProdutoXCategoria)
        {
            if (listProdutoXCategoria!=null)
                foreach (produtoxcategoria produtoXCategoria in listProdutoXCategoria)
                    DeletaProdutoxCategoria(produtoXCategoria);
        }

        public void AddProdutoxCategoria(produtoxcategoria produtoXCategoria)
        {
            modelo.AddToprodutoxcategoria(produtoXCategoria);
            modelo.SaveChanges();
        }
        public void AddProdutoxCategoria(List<produtoxcategoria> listProdutoXCategoria)
        {
            if (listProdutoXCategoria != null)
                foreach (produtoxcategoria produtoXCategoria in listProdutoXCategoria)
                    AddProdutoxCategoria(produtoXCategoria);
        }

        #region ProdutoXSubFamilia
        public List<produtoxsubfamilia> RecuperaProdutoXSubFamilia(int? idProduto, int? idSubFamilia)
        {
            try
            {
                IQueryable<produtoxsubfamilia> query = modelo.produtoxsubfamilia;
                if (idProduto != null) query = query.Where(i => i.IdProduto == idProduto);
                if (idSubFamilia != null) query = query.Where(i => i.IdSubFamilia == idSubFamilia);
                var retornaLista = from p in query select p;
                if (retornaLista.Count() > 0) return retornaLista.ToList();
                else return null;
            }
            catch { throw; }
        }

        public void DeletaProdutoXSubFamilia(produtoxsubfamilia produtoXSubFamilia)
        {
            try
            {
                EntityKey key = new EntityKey(modelo.DefaultContainerName + ".produtoxsubfamilia", "IdProdutoXSubFamilia", produtoXSubFamilia.IdProdutoXSubFamilia);
                modelo.DeleteObject(modelo.GetObjectByKey(key));
                modelo.SaveChanges();
            }
            catch { throw; }
        }
        public void DeletaProdutoXSubFamilia(List<produtoxsubfamilia> listProdutoXSubFamilia)
        {
            if (listProdutoXSubFamilia != null)
                foreach (produtoxsubfamilia produtoXSubFamilia in listProdutoXSubFamilia)
                    DeletaProdutoXSubFamilia(produtoXSubFamilia);
        }

        public void AddProdutoXSubFamilia(produtoxsubfamilia produtoXSubFamilia)
        {
            modelo.AddToprodutoxsubfamilia(produtoXSubFamilia);
            modelo.SaveChanges();
        }
        public void AddProdutoXSubFamilia(List<produtoxsubfamilia> listProdutoXSubFamilia)
        {
            if (listProdutoXSubFamilia != null)
                foreach (produtoxsubfamilia produtoXSubFamilia in listProdutoXSubFamilia)
                    AddProdutoXSubFamilia(produtoXSubFamilia);
        }
        #endregion
    }

}
